/** 
 * 包名: package com.raising.system.interceptor; <br/> 
 * 添加时间: 2017年11月17日 上午9:29:57 <br/> 
 */
package com.ferryc.commons.scan;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;

/**
 * 类名: MyExceptionHandlerExceptionResolver <br/>
 * 作用：TODO(简单一句话描述)<br/>
 * 创建者: Ferry Chen. <br/>
 * 添加时间: 2017年11月17日 上午9:29:57 <br/>
 */
public class MyExceptionHandlerExceptionResolver extends ExceptionHandlerExceptionResolver {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	public MyExceptionHandlerExceptionResolver() {
		List<HandlerMethodArgumentResolver> list = new ArrayList<HandlerMethodArgumentResolver>();
		list.add(new ServletModelAttributeMethodProcessor(true));
		this.setCustomArgumentResolvers(list);
	}

	@Override
	protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
		ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
		if (null != exception) {
			logger.error(exception.getMessage(), exception);
		}
		if (exceptionHandlerMethod == null) {
			return null;
		}

		// ServletModelAttributeMethodProcessor
		// 内部会使用传递进来的WebDataBinderFactory参数，该参数由ServletInvocableHandlerMethod提供
		exceptionHandlerMethod.setDataBinderFactory(new ServletRequestDataBinderFactory(null, null));

		exceptionHandlerMethod.setHandlerMethodArgumentResolvers(getArgumentResolvers());
		exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(getReturnValueHandlers());

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();

		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking @ExceptionHandler method: " + exceptionHandlerMethod);
			}
			exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
		} catch (Exception invocationEx) {
			logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
			return null;
		}

		if (mavContainer.isRequestHandled()) {
			return new ModelAndView();
		} else {
			ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
			mav.setViewName(mavContainer.getViewName());
			if (!mavContainer.isViewReference()) {
				mav.setView((View) mavContainer.getView());
			}
			return mav;
		}
	}

}
